home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
FIREKIT.ZIP
/
FLAMES.ASM
< prev
next >
Wrap
Assembly Source File
|
1996-05-27
|
12KB
|
548 lines
IDEAL
JUMPS
P386 ; 386 specific opcodes and shit allowed.
;************************************************************************
;
; FIREKIT v1.0
;
; by
;
; John W. Ractliff
; 70253.3237@compuserve.com
; jratclif@inlink.com
;
; 32bit DOS4GW application.
; Will run in Microsoft Windowss 32 bit mode.
; Source code in ANSI C and Turbo Assembler
;
;
;The enclosed software was written by John W. Ratcliff on May 27, 1996.
;As of this date I am releasing this software into the public domain.
;
;I am releasing this software into the public domain, hopefully, to make
;a point. I would like to demonstrate how to write source code that is
;useful to other people. I was looking at some of the various flame
;algorithms and source code examples and in each case they were such hard
;coded demos nobody could actually get them integrated into an
;application.
;************************************************************************/
MODEL FLAT,C ;32-bit OS/2 model
public FlameStart
public FlameFrame
public FlameCopy
public FlameStop
public FlameZeroScreen
public FlameImage
public FlameDAC
public FlamePal
public FlameCopyTranslate
public FlameClosestColor
Macro useall
uses ebx,ecx,edx,esi,edi
endm
FWID equ 320 ; default flame width.
Struc FLAMESPEC
width dd ? ; width of flame buffer.
height dd ? ; height of flame buffer.
fsize dd ? ; length, width*height, of flame buffer.
andmask dd ? ; fuel dump and mask, controls how many dumps are made.
flame1 dd ? ; address of flame buffer #1
flame2 dd ? ; address of flame buffer #2
jitter dd ? ; 512 long word jitter table.
seed dd ? ; random number seed.
fheight dd ? ; flame consumption value.
fuel dd ? ; size of fuel dumps.
fuelbase dd ? ; base fuel fed at bottom.
fire8 dd ? ; flag is true if doing 8 pixel average of fire.
ScreenX dd ? ; destination screen x copy location.
ScreenY dd ? ; destination screen y copy location.
ctrans db 256 dup(?) ;the color translation table if used.
Ends
DATASEG
lastwid dd FWID ; last width self-modified in the code.
label pal byte
rept 8
db 0,0,0
endm
i=0
rept 8
db i*2, 0, 0
i=i+1
endm
i=0
rept 16
db 16+47*i/16, 0, 0
i=i+1
endm
i=0
rept 24
db 63, 21*i/8, 0
i=i+1
endm
i=0
rept 24
db 63, 63, 21*i/8
i=i+1
endm
db 179*3 dup(63)
CODESEG
;; Init the screen.
Proc C FlameStart near
useall
mov eax, 0013h ; mode 13h
int 10h ; turn 320x200 mode on.
mov edx,3c8h ; set the color palette.
xor al,al
out dx,al
inc dx
mov ecx,256*3
lea esi,[pal]
@@p1: mov al, [esi]
out dx, al
inc esi
dec ecx
jnz @@p1
ret
endp
Proc C FlameFrame near
arg fl:dword
local fuel:dword
useall
mov ebx,[fl]
mov eax,[(FLAMESPEC ebx).width]
cmp eax,[lastwid] ; same as current modification?
je @@OK
;; Here we must self-modify all of the instructions which have
;; hard-coded offsets based on the width of the image being filtered.
;; There is no way around this self-modified code, period!
;; The first 8 instructions to modify all have an offset of 3 bytes
;; While MOD9-MOD12 have an offset of 2 bytes
mov edx,eax ; EDX has -width.
neg edx ;
mov [MOD1+3],edx ; -WIDTH
mov [MOD2+3],eax ; +WIDTH
inc eax ; WIDTH+1
neg eax ; Make it negative
mov [MOD3+3],eax ; -(WIDTH+1)
neg eax ; +(WIDTH+1)
mov [MOD4+3],eax
sub eax,2 ; now equal width-1
neg eax ; -(width-1)
mov [MOD5+3],eax
neg eax ; now + (width-1)
mov [MOD6+3],eax ;
inc eax ; back to positive width.
mov [MOD7+3],edx ; -width
mov [MOD8+3],eax ; +width
mov [MOD9+2],edx ; -width
mov [MOD10+2],eax ; +width
mov [MOD11+2],edx ; -width
mov [MOD12+2],eax ; +width
@@OK:
mov eax,[(FLAMESPEC ebx).fuel]
mov [fuel],eax
mov esi,[(FLAMESPEC ebx).flame1] ; current source frame.
mov edi,[(FLAMESPEC ebx).flame2] ; current destination frame.
add esi,[(FLAMESPEC ebx).width]
inc esi ; width +1
inc edi ; base address of desintation.
;; ECX = wid*hit-(wid+2)
mov ecx,[(FLAMESPEC ebx).fsize] ; Length of buffer.
mov eax,[(FLAMESPEC ebx).width] ; minus width+2
shl eax,1
add eax,2
sub ecx,eax
;; Each pixel is equal to the mean sum of the one left/right, up and down
;; on the previous frame.
mov edx,[(FLAMESPEC ebx).fheight] ; height of flame.
cmp [(FLAMESPEC ebx).fire8],0 ; doing normal 4 pixel average?
je @@l1
@@k1:
LABEL MOD1 DWORD
movzx ebx,[byte esi-FWID] ; get first byte.
LABEL MOD2 DWORD
movzx eax,[byte esi+FWID] ; get next byte
add ebx,eax ; add into total.
movzx eax,[byte esi-1] ; get next byte.
add ebx,eax ; add into total.
movzx eax,[byte esi+1] ; get fourth byte
add ebx,eax ; have complte summation.
LABEL MOD3 DWORD
movzx eax,[byte esi-(FWID+1)]
add ebx,eax
LABEL MOD4 DWORD
movzx eax,[byte esi+(FWID+1)]
add ebx,eax
LABEL MOD5 DWORD
movzx eax,[byte esi-(FWID-1)]
add ebx,eax
LABEL MOD6 DWORD
movzx eax,[byte esi+(FWID-1)]
add eax,ebx
shr eax,3
sub eax,edx
jns @@k2
xor eax,eax
@@k2: mov [edi],al ; store result.
inc edi
inc esi
dec ecx
jnz @@k1
jmp @@cont ; re-enter rest of code.
@@l1:
LABEL MOD7 DWORD
movzx ebx,[byte esi-FWID] ; get first byte.
LABEL MOD8 DWORD
movzx eax,[byte esi+FWID] ; get next byte
add ebx,eax ; add into total.
movzx eax,[byte esi-1] ; get next byte.
add ebx,eax ; add into total.
movzx eax,[byte esi+1] ; get fourth byte
add eax,ebx ; have complte summation.
shr eax,2
sub eax,edx
jns @@l2
xor eax,eax
@@l2:
mov [edi],al ; store result.
inc edi
inc esi
dec ecx
jnz @@l1
@@cont:
;; Randomize the bottom 3 scanlines of next frame.
mov edx,69069 ; a prime number.
mov ebx,[fl] ; address of flamespec
mov edi,[(FLAMESPEC ebx).flame2] ; destination.
mov eax,[(FLAMESPEC ebx).width]
shl eax,1
add edi,[(FLAMESPEC ebx).fsize] ; add size of buffer.
sub edi,eax ; less width *2
mov ecx,[(FLAMESPEC ebx).width] ; randomize scanline.
mov eax,[(FLAMESPEC ebx).seed]
mov ebx,[(FLAMESPEC ebx).fuelbase]
shl ebx,8
;; Adding fuel to the fire.
@@l3:
imul eax,edx
inc eax ; Plus 1
mov bl,ah
and bl,0fh
add bl,bh
LABEL MOD9 DWORD
mov [edi-FWID],bl
imul eax,edx
inc eax
mov bl,ah
and bl,0fh
add bl,bh
mov [edi],bl
imul eax,edx
inc eax
mov bl,ah
and bl,0fh
add bl,bh
add bl,bh
LABEL MOD10 DWORD
mov [edi+FWID],bl
inc edi
dec ecx
jnz @@l3
;; This is a random-jitter function that forces the flames to bubble/roil.
;; This forces raw fuel into a random number of pixels.
push eax ; preserve current random number.
mov ebx,[fl] ; address of flamespec.
mov esi,[(FLAMESPEC ebx).flame2]
add esi,[(FLAMESPEC ebx).fsize]
mov eax,[(FLAMESPEC ebx).width]
shl eax,1
sub esi,eax ; bottom scanline-2
pop eax
imul eax,edx
inc eax
mov cl,al
and ecx,[(FLAMESPEC ebx).andmask] ; and
jz @@EMPTY
; the number of pixel to add fuel to.
mov edi,[(FLAMESPEC ebx).jitter] ; get 512 dword jitter table.
;; EAX/EDX random number.
;; EBX - scratch.
;; ECX - Count.
;; ESI - base for scanline.
;; EDI - base address of 512 entry jitter table.
@@l4: imul eax,edx
inc eax ; compute random
mov ebx,eax ; random into EBX
xchg bl,bh ; swap low/high to make it interesting.
and ebx,511 ; top 512 entries.
mov ebx,[edi+ebx*4] ; pull *valid* offset from jitter table.
add ebx,esi ; plus base.
push eax ; preserve current random number.
;; Fuel Dump
mov eax,[fuel]
LABEL MOD11 DWORD
mov [ebx-FWID],al ; dump line above.
LABEL MOD12 DWORD
mov [ebx+FWID],al ; dump line below.
mov [ebx-1],al ; dump left
mov [ebx+1],al ; dump right
mov [ebx],al ; dump current.
pop eax
dec ecx
jnz @@l4
@@EMPTY:
mov ebx,[fl]
mov [(FLAMESPEC ebx).seed],eax
mov eax,[(FLAMESPEC ebx).flame1]
mov ecx,[(FLAMESPEC ebx).flame2]
mov [(FLAMESPEC ebx).flame1],ecx
mov [(FLAMESPEC ebx).flame2],eax
ret
endp
;; This actually copies the flame to the screen, and then flip/flops the
;; buffers.
Proc C FlameCopy near
arg fl:dword
useall
mov ebx,[fl]
mov esi,[(FLAMESPEC ebx).flame1]
lea edi,[0A0000h] ; in Watcom DOS4gw, hard coded physical address.
mov eax,320
imul [(FLAMESPEC ebx).ScreenY]
add eax,[(FLAMESPEC ebx).ScreenX]
add edi,eax ; dest screen scanline.
mov ecx,[(FLAMESPEC ebx).width]
shr ecx,2 ; /4 movsd
mov edx,[(FLAMESPEC ebx).height]
sub edx,3
@@GO:
push edi
push ecx
rep movsd
pop ecx
pop edi
add edi,320
dec edx
jnz @@GO
ret
endp
Proc C FlameStop near
useall
mov eax,03h
int 10h ; back to text mode.
ret
endp
Proc C FlameZeroScreen near
useall
mov edi,0A0000h
xor eax,eax
mov ecx,64000/4
rep stosd
ret
endp
Proc C FlameImage near
arg image:dword
useall
mov esi,[image]
mov edi,0A0000h
mov ecx,64000/4
rep movsd
ret
endp
Proc C FlameDAC near
arg fpal:dword
useall
mov edx,3c8h ; set the color palette.
xor al,al
out dx,al
inc dx
mov ecx,256*3
mov esi,[fpal]
@@p1: mov al, [esi]
shr al,2 ; into 5 bit format.
out dx,al
inc esi
dec ecx
jnz @@p1
ret
endp
Proc C FlamePal near
arg fpal:dword
useall
mov edi,[fpal]
lea esi,[pal]
mov edx,3c8h ; set the color palette.
xor al,al
out dx,al
inc dx
mov ecx,256*3
@@p1: mov al,[esi]
shl al,2
mov [edi],al
shr al,2
out dx, al
inc esi
inc edi
dec ecx
jnz @@p1
ret
endp
;; This actually copies the flame to the screen, and then flip/flops the
;; buffers.
Proc C FlameCopyTranslate near
arg fl:dword,image:dword
useall
mov ebx,[fl]
mov esi,[(FLAMESPEC ebx).flame1]
mov edi,[image] ; in Watcom DOS4gw, hard coded physical address.
mov eax,320
imul [(FLAMESPEC ebx).ScreenY]
add eax,[(FLAMESPEC ebx).ScreenX]
add edi,eax ; dest screen scanline.
mov ecx,[(FLAMESPEC ebx).width]
mov edx,[(FLAMESPEC ebx).height]
lea ebx,[(FLAMESPEC ebx).ctrans] ; base address of color translate table.
sub eax,eax ; zero out EAX
sub edx,3 ; Don't do bottom 3 scanlines.
@@GO:
push edi
push ecx
@@MERG: mov al,[esi]
inc esi
cmp al,4
jbe @@M0
mov al,[ebx+eax] ; color translate flame.
mov [edi],al
@@M0: inc edi
dec ecx
jnz @@MERG
pop ecx
pop edi
add edi,320
dec edx
jnz @@GO
ret
endp
Macro Error COLOR
LOCAL @@OK
xor eax,eax
lodsb ; Get color.
sub eax,[COLOR]
jns @@OK
neg eax
@@OK: push ebx ; Save current error.
mov ebx,eax ; Into BX, difference.
mul bl ; Square it.
pop ebx ; Restore current error.
add ebx,eax ; Add into total error.
endm
Proc C FlameClosestColor near
ARG PALETTE:DWORD,R:DWORD,G:DWORD,B:DWORD
LOCAL DOMINANT:WORD
useall
mov esi,[PALETTE]
mov edx,0FFFFFFFFh ; Minimum error initially found.
xor ecx,ecx ; for all 256 colors.
@@FIND:
mov al,[esi] ; Get red
mov ah,[esi+1] ; Get green.
mov bl,[esi+2] ; Get blue.
xor ebx,ebx ; Total error.
Error R
Error G
Error B
cmp ebx,edx ; Less then previous minimum error?
jae @@NOT
mov edx,ebx ; New minimum error.
mov edi,ecx ; Save minimum error loc.
@@NOT: inc ecx
cmp ecx,256
jne @@FIND
mov eax,edi ; Closest match.
ret
endp
END